package com.platform.api;

import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;

import cn.beecloud.BCCache;
import cn.beecloud.BeeCloud;
import com.platform.annotation.IgnoreAuth;
import com.platform.entity.ApiAmountBillVo;
import com.platform.entity.UserVo;
import com.platform.service.ApiAmountBillService;
import com.platform.service.ApiUserService;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by zhurusen on 2018/5/19
 */
@RestController
@RequestMapping(value = "/api/webhook")
public class BeeCloudWebhookReceiver {

    @Autowired
    private ApiAmountBillService apiAmountBillService;
    @Autowired
    private ApiUserService apiUserService;

    public static final String APP_ID = "e74404dd-ae2d-4bc8-bfb7-b414a56887d1";
    public static final String TEST_SECRET = "5baac383-0dec-4648-b73b-7b9e7bff783e";
    public static final String APP_SECRET = "4f6bec4a-f5a8-44c0-8638-2cdff63b92fe";
    public static final String MASTER_SECRET = "2309ab21-4a52-4abc-98ba-a0c50cf281d8";

    boolean verifySign(String text, String masterKey, String signature) {
        boolean isVerified = verify(text, signature, masterKey, "UTF-8");
        if (!isVerified) {
            return false;
        }
        return true;
    }

    boolean verify(String text, String sign, String key, String inputCharset) {
        text = text + key;
        String mysign = DigestUtils.md5Hex(getContentBytes(text, inputCharset));
        return mysign.equals(sign);
    }

    byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }

    @IgnoreAuth
    @RequestMapping("/receiver")
    public String receiver(HttpServletRequest request) {
        String result = "";
        BeeCloud.registerApp(APP_ID, "", APP_SECRET, MASTER_SECRET);
        BeeCloud.setSandbox(false);
        StringBuffer json = new StringBuffer();
        String line = null;

        try {
            request.setCharacterEncoding("utf-8");
            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                json.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject jsonObj = JSONObject.fromObject(json.toString());

        String signature = jsonObj.getString("signature");
        String transactionId = jsonObj.getString("transaction_id");
        String transactionType = jsonObj.getString("transaction_type");
        String channelType = jsonObj.getString("channel_type");
        String transactionFee = jsonObj.getString("transaction_fee");
        System.out.println("___支付回调___" + transactionId);

        StringBuffer toSign = new StringBuffer();
        toSign.append(BCCache.getAppID()).append(transactionId)
                .append(transactionType).append(channelType)
                .append(transactionFee);
        boolean status = verifySign(toSign.toString(), MASTER_SECRET, signature);
        if (status) { //验证成功

            result = "success"; //请不要修改或删除
            // 此处需要验证购买的产品与订单金额是否匹配:
            // 验证购买的产品与订单金额是否匹配的目的在于防止黑客反编译了iOS或者Android app的代码，
            // 将本来比如100元的订单金额改成了1分钱，开发者应该识别这种情况，避免误以为用户已经足额支付。
            // Webhook传入的消息里面应该以某种形式包含此次购买的商品信息，比如title或者optional里面的某个参数说明此次购买的产品是一部iPhone手机，
            // 开发者需要在客户服务端去查询自己内部的数据库看看iPhone的金额是否与该Webhook的订单金额一致，仅有一致的情况下，才继续走正常的业务逻辑。
            // 如果发现不一致的情况，排除程序bug外，需要去查明原因，防止不法分子对你的app进行二次打包，对你的客户的利益构成潜在威胁。
            // 如果发现这样的情况，请及时与我们联系，我们会与客户一起与这些不法分子做斗争。而且即使有这样极端的情况发生，
            // 只要按照前述要求做了购买的产品与订单金额的匹配性验证，在你的后端服务器不被入侵的前提下，你就不会有任何经济损失。

            // 处理业务逻辑
            ApiAmountBillVo amountBillVo = apiAmountBillService.selecyByBillNo(transactionId);

            if (amountBillVo != null && amountBillVo.getStatus() == 1) {
                UserVo userVo = apiUserService.queryObject(amountBillVo.getUserId());

                userVo.setAvailable_amount(userVo.getAvailable_amount().add(amountBillVo.getAmount()));
                userVo.setWithdraw_amount(userVo.getWithdraw_amount().add(amountBillVo.getAmount()));
                apiUserService.update(userVo);

                amountBillVo.setStatus(3);
                apiAmountBillService.updata(amountBillVo);
            }


        } else { //验证失败
            result = "fail";
        }
        return result;
    }

}
